CloudWatch アラームがアラーム状態になった際 EventBridge の入力トランスフォーマーを使わず Step Functions でメール件名と本文をカスタマイズし SNS からメール通知する

CloudWatch アラームがアラーム状態になった際 EventBridge の入力トランスフォーマーを使わず Step Functions でメール件名と本文をカスタマイズし SNS からメール通知する

EventBridge の入力トランスフォーマー(Input Transformer)や Lambda は使わず、Step Functions にカスタマイズ処理させます。
Clock Icon2024.10.21

コーヒーが好きな emi です。

今更ですが、CloudWatch アラームがアラーム状態になった際 EventBridge から Step Functions でメール件名と本文をカスタマイズし SNS からメール通知する構成をやってみました。
EventBridge の入力トランスフォーマー(Input Transformer)や Lambda は使わず、Step Functions にメール件名と本文のカスタマイズ処理をさせます。

イメージ図と背景

以下のように、1 つの Step Function ステートマシンで SNS メール通知の件名と本文をカスタマイズします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_1

AWS からの通知を SNS 経由でメール受信すると、件名がデフォルトの『AWS Notification Message』となり、内容がわかりにくかったり、本文にそのまま JSON が貼り付けられて見づらいことがあります。

Lambda を使えば通知の柔軟なカスタマイズが可能ですが、コードやライブラリバージョンの管理が必要です。できれば Step Functions にすべての処理をお任せしたいです。
https://aws.amazon.com/jp/builders-flash/202409/execute-task-spep-functions/

また、EventBridge の入力トランスフォーマー(Input transformer)でメールの本文をカスタマイズする場合、各 Event 毎に入力トランスフォーマーを設定する必要があります。
できればこちらも毎回設定するのではなく、1 つの Step Functions ステートマシンにメール件名と本文のカスタマイズをお任せしたいです。また、EventBridge だけではメールの件名までカスタマイズできないので、やはり Step Functions が必要です。

SNS トピックとサブスクリプションの作成

では SNS トピックとサブスクリプションを作成していきます。SNS コンソールで「トピックの作成」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_2

スタンダードトピックを選択し、トピック名と表示名を設定して作成します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_3

サブスクリプションも作成します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_4

今回は E メールを選択して作成します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_5

サブスクリプションのステータスが「保留中の確認」になります。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_6

以下の手順で、メール通知の停止(Unsubscribe)リンクを無効化した状態でサブスクリプションを確認します。
https://dev.classmethod.jp/articles/prevent-unsubscribe-all-sns-topic/

上記ブログの手順で確認すると、メール通知の停止(Unsubscribe)リンクを無効化した状態でサブスクリプションが「確認済み」になります。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_8

Step Functions ステートマシンの作成

Step Functions コンソールでステートマシンを作成します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_9

テンプレートがいろいろありますが、「Blank」のまま「選択」で進みます。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_10

コードで以下を貼り付けます。

{
  "Comment": "CloudWatch Alarm Notification Workflow",
  "StartAt": "Check Alarm State",
  "States": {
    "Check Alarm State": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.detail.state.value",
          "StringEquals": "ALARM",
          "Next": "Format Message"
        }
      ],
      "Default": "Do Nothing"
    },
    "Format Message": {
      "Type": "Pass",
      "Parameters": {
        "subject.$": "States.Format('CloudWatchアラーム通知: {}', $.detail.alarmName)",
        "message.$": "States.Format('アラーム名: {}\n状態: {}\n理由: {}\n時刻: {}', $.detail.alarmName, $.detail.state.value, $.detail.state.reason, $.time)"
      },
      "Next": "Send SNS"
    },
    "Send SNS": {
      "Type": "Task",
      "Resource": "arn:aws:states:::sns:publish",
      "Parameters": {
        "TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:SNS-Step-Functions-format-test",
        "Message.$": "$.message",
        "Subject.$": "$.subject"
      },
      "End": true
    },
    "Do Nothing": {
      "Type": "Pass",
      "End": true
    }
  }
}

"TopicArn" には作成した SNS トピックの ARN を入力してください。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_11

画面上部のステートマシン名の横の鉛筆マークをクリックすると、ステートマシンの設定画面が開きます。

  • ステートマシン名:任意のステートマシン名を入力します。
  • タイプ:標準
  • 実行ロール:新しいロールを作成

emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_12

  • ログレベル:ERROR
    • ステートマシンの実行が失敗したときのために ERROR ログに実行データを含めて保存します。システムの要件に合わせてカスタムしてください。

emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_13

  • CloudWatch ロググループ:新しいロググループを作成

emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_14

他の設定値はデフォルトで「確認」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_15

ステートマシンができるまで 1 分ほどかかります。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_16

ステートマシンの IAM ロールは以下のような権限が付与されて作成されます。

許可

CloudWatchLogsDeliveryFullAccessPolicy-xxxxxxxxxxxx
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogDelivery",
                "logs:GetLogDelivery",
                "logs:UpdateLogDelivery",
                "logs:DeleteLogDelivery",
                "logs:ListLogDeliveries",
                "logs:PutResourcePolicy",
                "logs:DescribeResourcePolicies",
                "logs:DescribeLogGroups"
            ],
            "Resource": "*"
        }
    ]
}
SnsPublishScopedAccessPolicy-xxxxxxxxxxxx
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": [
                "arn:aws:sns:ap-northeast-1:123456789012:SNS-Step-Functions-format-test"
            ]
        }
    ]
}
XRayAccessPolicy-xxxxxxxxxxxx
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "xray:PutTraceSegments",
                "xray:PutTelemetryRecords",
                "xray:GetSamplingRules",
                "xray:GetSamplingTargets"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_47

信頼関係

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "states.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

ステートマシンのテスト実行

Step Functions ステートマシンが正しく作成できたかテスト実行してみます。テスト実行のためにサンプルの入力をコピーします。

サンプルの入力コードは EventBridge からコピーします。EventBridge ルールで「ルールの作成」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_40

途中でキャンセルするので名前は適当で、他はそのまま次へ進みます。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_41

サンプルイベントで「AWS イベント」、「CloudWatch Alarm State Change」を選択すると、サンプルイベントが表示されます。これをコピーしてテキストにメモしておきます。メモできたら、キャンセルをクリックしてルールの作成をやめます。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_42

Step Functions ステートマシンのコンソールに戻ります。「実行を開始」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_43

「入力 - オプション」に、コピーしたサンプルイベントを貼り付けて「実行を開始」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_44

実行が成功するはずです。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_45

メールを見ると、Step Functions ステートマシンの作成時に設定した通りにカスタマイズされたメールが届いています。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_46

CloudWatch アラームの作成

通知させる CloudWatch アラームを作成します。何でもよいのですが、今回は適当な EC2 インスタンスの CPUUtilization のアラームを設定しましょう。EC2 インスタンスの「モニタリング」で CPU 使用率を展開します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_17

「メトリクスで表示」をクリックし、
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_18

「アクション」のベルマークをクリックしてアラームを作成します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_19

統計は最大にしておきました。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_20

10% を超えたときにアラーム状態になるように設定します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_21

アクションの設定では何も設定しなくて OK です。「通知」は右上の「削除」をクリックして削除しておきます。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_22

アクションに何も設定されていない状態になりました。「次へ」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_23

アラーム名を設定し「次へ」をクリックすると確認画面に遷移します。そのままアラームを作成します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_24

作成されたアラームの詳細で画面下部の「EventBridge ルールを表示」をクリックすると、EventBridge ルールを作成する際に必要になるカスタムイベントパターンが表示されます。これをコピーしてテキストにメモしておきます。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_25

こんな感じのカスタムイベントパターンがコピーできます。

カスタムイベントパターン
{
  "source": [
    "aws.cloudwatch"
  ],
  "detail-type": [
    "CloudWatch Alarm State Change"
  ],
  "resources": [
    "arn:aws:cloudwatch:ap-northeast-1:123456789012:alarm:<アラーム名>"
  ]
}

EventBridge ルールの作成

EventBridge ルールを作成します。EventBridge コンソールで「ルールを作成」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_26

名前、説明を入力します。ルールタイプは「イベントパターンを持つルール」を選択して「次へ」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_27

イベントソースは「その他」を選択し、
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_28

そのままスクロールしてイベントパターンを入力します。先ほど CloudWatch アラームの作成時にコピーしておいたイベントパターンを貼り付けます。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_29

ターゲットの選択では作成した Step Functions ステートマシンを選択します。実行ロールは新しいロールを作成を選択します。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_30

「ターゲット入力を設定」で「一致したイベント」になっているのを確認し「次へ」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_31

確認画面が表示されます。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_32

「ルールの作成」をクリックします。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_33

EventBridge ルールができました。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_34

「イベントパターン」タブはこのようになっています。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_35-2

「ターゲット」タブはこのようになっています。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_36-2

EventBridge ルールターゲットタブに表示されている IAM ロールは以下のような権限が付与されています。

Amazon_EventBridge_Invoke_Step_Functions_xxxxxxxxx
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "states:StartExecution"
            ],
            "Resource": [
                "arn:aws:states:ap-northeast-1:123456789012:stateMachine:SNS-Step-Functions-format-test"
            ]
        }
    ]
}

信頼関係

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

CloudWatch アラームをアラーム状態にする

CloudWatch アラームをアラーム状態にして、カスタマイズされた件名と本文のメールが通知されるか確認します。実際に EC2 に負荷をかけてもいいのですが、アラーム状態を変更する API があるのでこれを使います。詳細は以下のブログを参照ください。
https://dev.classmethod.jp/articles/tsnote-cloudwatch-alarm-test-001/

AWS CLI からアラームの状態を変更します。
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudwatch/set-alarm-state.html

CloudShell で、以下のコマンドを実行します。

aws cloudwatch set-alarm-state \
  --alarm-name "<アラーム名>" \
  --state-value ALARM \
  --state-reason "test"

実行結果例

[cloudshell-user@ip-10-130-33-150 ~]$ aws cloudwatch set-alarm-state \
>   --alarm-name "EC2 CPUUtilization" \
>   --state-value ALARM \
>   --state-reason "test"
[cloudshell-user@ip-10-130-33-150 ~]$ 

上記コマンドを実行すると、一時的にアラーム状態になります。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_37

アラーム状態はすぐに正常に戻ります。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_38

メール通知確認

カスタマイズされた件名と本文のメール通知が受信できました。
emiki_cloudwatchalarm_eventbridge_stepfunctions_sns_mail_39

参考

https://dev.classmethod.jp/articles/human-readable-mail-from-cloudwatch/

https://dev.classmethod.jp/articles/send-japanese-email-cloudwatchalarm-snswith-cfn/

https://dev.classmethod.jp/articles/change-default-subject-for-amazon-sns-email-notifications-with-aws-step-functions-and-amazon-eventbridge-input-transformer/

https://repost.aws/ja/knowledge-center/eventbridge-human-readable-notifications

https://repost.aws/ja/knowledge-center/change-sns-email-for-eventbridge

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.